/*
 * Copyright (c) 2018-2024 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#ifndef COMMON_CHANNEL_H
#define COMMON_CHANNEL_H

#include "list.h"
#include "xdrbase.h"

#define VALID_IO_ERR(x) ((x) == EWOULDBLOCK || (x) == EINTR || (x) == EAGAIN)
#define BAD_IO_ERR(x)   ( ! VALID_IO_ERR(x))

enum inout
{
    IN = 1,
    OUT,
};

struct chan_data
{
    struct chan_data *forw;
    struct chan_data *back;
    struct header hdr;       /* header of the data */
    char *data;              /* data to be sent, or received data */
    unsigned int datalen;    /* length of the data */
    enum inout stream;
};

enum chan_state
{
    CHANNEL_FREE = 1,
    CHANNEL_CONN,
    CHANNEL_DISC,
    CHANNEL_SEND,
    CHANNEL_RECV,
    CHANNEL_WAIT,
    CHANNEL_LONGCONN,
};

struct channel
{
    int fd;
    enum chan_state state;
    LIST_T *senddatalist;
    LIST_T *recvdatalist;
};

extern int gf_chan_init(void);
extern int gf_get_epfd(void);
extern int gf_init_server(struct sockaddr_in *);
extern int gf_get_sockport(void);
extern void gf_chan_close(int);
extern void gf_child_chan_close(int);
extern void gf_chan_close_accept(void);
extern int gf_new_conn(int);
extern int gf_connect(const char *, int, int);
extern int gf_connect_list(const char *, int, int);
extern int gf_connect_addr(struct sockaddr *, int, int);
extern int gf_chan_state(int, enum chan_state);
extern int gf_get_chan_state(int);
extern int gf_recv_data(int);
extern int gf_send_data(int);
extern int gf_add_data(int, char *, unsigned int);
extern int gf_get_data(int, LIST_T **);
extern int gf_clean_recvdata(int, struct chan_data *);
extern bool_t gf_check_longconn(int);
extern unsigned int gf_chan_read(int, char *, unsigned int, int);
extern unsigned int gf_chan_write(int, const char *, unsigned int, int);
extern int gf_read_select(int, struct timeval);

extern int gf_handle_socket(int);
extern int gf_sendback_header(int, struct header *);
extern int gf_sendback_header2(int, struct header *);
extern int gf_errorback(int, struct header *, char *);
extern int gf_callmaster(const char *, int, int, int, int, unsigned int, const char *,
                         struct header *, char **, int *);
extern int gf_callslave(const char *, int, int, int, unsigned int, const char *,
                        struct header *, char **, int *);
extern int gf_read_reply(int,  int, struct header *, char **);
extern char *gf_get_master(void);
extern unsigned int gf_get_fdlist(int **);

extern int gf_max_channels(void);
extern void gf_set_nonblocking(int);
extern void gf_set_blocking(int);
extern int gf_sock_bind(int, struct sockaddr *, int);
extern char *gf_sockaddr_str(struct sockaddr_in *, char *);
extern void gf_sleep(int);

#endif
